#include "matrix_keyboard.h"
#include "polsys.h"



#if ((_KEYBOARD_VER <= 1)||(_KEYBOARD_HOR <=1))
    #error "param error, or you do't need matrix keyboard component."
#endif

// #define _KEY_BUFF_DEFAULT   \
// {\
//     {\
//         0,\
//         0\
//     }\
// }


static keyboard_t mKB;

static polsys_task_t mMatrixKeyboardTask;


static void MatrixKeyboardLoop();


IN_LINE void Keyboard_Init()
{
    memset(&mKB, 0, sizeof(keyboard_t));
    Polsys_TaskInit(&mMatrixKeyboardTask, MatrixKeyboardLoop, _KEYBOARD_SCAN_INTERVAL);
}

IN_LINE key_value_t Keyboard_GetLastKey()
{
#ifdef _KEYBOARD_CONVERT_KEY_VALUE
    #error "not support yet."
#else
    return mKB.LastKey;
#endif
}

IN_LINE key_status_t Keyboard_GetLastStatus()
{
    return mKB.LastStatus;
}

IN_LINE key_buff_t * Keyboard_GetBuff()
{
    return &mKB.KeyBuff;
}

void Keyboard_SetEventCb(void (*EventCb)(const keyboard_t * Sender))
{
    mKB.EventCb = EventCb;
}

// 内部函数

// 通知变化
// hor_num: 行号（对应缓存角标）
// charge_info: 变化信息，对应当前行中哪一列有变化，有变化的列对应位为1.
// current_value: 当前行中每一个按钮的状态，对应位1表示按下。
static void NotifyChange(const u8 hor_num, const key_ver_t charge_info, const key_ver_t current_value)
{
    u8 i;

    mKB.LastKey.Hor = hor_num; // 保存行号
    for(i=0; i<_KEYBOARD_VER; i++)  // 依次判断每一个按钮（当前行中的每一列）
    {
        key_ver_t ver_mask = 1 << i;
        if(charge_info & ver_mask)
        {
            mKB.LastKey.Ver = i;   // 保存列号
            mKB.LastStatus = (current_value & ver_mask)?KEY_STATUS_PRESS:KEY_STATUS_RELEASE;    // 获取状态
            if(mKB.EventCb)mKB.EventCb(&mKB);
        }
    }
}

// 10ms执行一次
static void MatrixKeyboardLoop()
{
    key_ver_t ver_v;
    key_hor_t hor_v;
    // ver_v = _Keyboard_GetVer();
#if (_KEYBOARD_SCAN_MODE == 0)
    // if(ver_v != _KEYBOARD_IDLE_VER_VALUE)  // 有按键被按下
    // {
        u8 i;
        key_ver_t change;
        for(i = 0; i < _KEYBOARD_HOR; i++)
        {
            hor_v = ~(1<<i);
            _Keyboard_SetHor(hor_v);        // 让某一行输出L
            ver_v = ~_Keyboard_GetVer();    // 获取列值
            change = mKB.KeyBuff.Data[i] ^ ver_v;
            if(change != 0) // 本行有按键状态改变
            {
                mKB.KeyBuff.Data[i] = ver_v;    // 保存最新按键状态
                NotifyChange(i, change, ver_v); // 通知按键变化
            }
        }
    // }
    // else    // 没有任何按键被按下
    // {
    // }
#else
    #error "not suported yet."
#endif
}



